home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Sample Code / Newton Sample Code 1.2 / Communications / IRTimeSync-2 / IRTimeSync.text < prev    next >
Encoding:
Text File  |  1994-07-08  |  15.8 KB  |  466 lines  |  [TEXT/MPS ]

  1.  
  2. // ---- End Project Data ----
  3.  
  4.  
  5. // ---- File IRTimeSync.t ----
  6.  
  7. // Before Script for "vIRTimeSync"
  8. //    ===========================================================================================
  9. //    IRTimeSync
  10. //
  11. //    Copyright © 1994 Apple Computer, Inc.
  12. //    All rights reserved.
  13. //
  14. //    Modification Status
  15. //    YY/MM/DD    Name                Comments
  16. //    94/05/20    Jim Schram        Initial Development during World Wide Developers Conference
  17. //    94/05/25    Jim Schram        Released as |IRTimeSync:PIEDTS| version 2 sample code
  18. //    -------------------------------------------------------------------------------------------------------------
  19. //    NOTE:    Time synchronization is accurate +/- one second and currently does not account for beam time.
  20. //    ===========================================================================================
  21.  
  22. constant kDebugShowPhases := nil;                                                    // true to show phase codes in vTitle area
  23. constant kIdleFrequency := 135;                                                        // number of milliseconds between idles
  24. constant kTimeoutTicks := 900;                                                        // number of ticks to wait before timing out a connection
  25.  
  26. constant kPhase_Idle := 0;                                                                // phase codes for the vTimeMachine state machine
  27. constant kPhase_CountDown := 1;
  28. constant kPhase_Send := 2;    
  29. constant kPhase_Connecting := 3;
  30. constant kPhase_Receive := 5;
  31. constant kPhase_Listening := 6;
  32. constant kPhase_Abort := 7;
  33. constant kPhase_AbortQuiet := 8;
  34. constant kPhase_Disconnect := 9;
  35. constant kPhase_Disconnecting := 10;
  36. constant kPhase_Disconnected := 11;
  37.  
  38. //    -------------------------------------------------------------------------------------------------------------
  39.  
  40. constant kTitle := "Newton Time Synchronization Via IR Beam";            // title of the application
  41.  
  42. constant kMessage_Send := "Looking for receiver...";                        // progress/status messages
  43. constant kMessage_Receive := "Looking for sender...";
  44. constant kMessage_Stopping := "Stopping...";
  45. constant kMessage_Timeout := "No response.";
  46. constant kMessage_TimeHasBeenSet := "Time has been set.";
  47. constant kMessage_PortInUse := "IR port in use?";
  48. constant kMessage_GenericError := "An error occured!";
  49. DefConst('kMessage_BadTime, "Bad time value received." & unicodeCR & "Please try again.");
  50.  
  51. DefConst('kMessage_CountDownFunc,                                                // progress/status message constructor functions
  52.     func(pendingSeconds)
  53.     return "Time will be set in"
  54.                 && NumberStr(pendingSeconds)
  55.                 &&    if pendingSeconds = 1 then "second."
  56.                         else "seconds." & unicodeCR & "Please wait...");
  57.  
  58. DefConst('kMessage_IdleFunc,
  59.     func()
  60.     begin
  61.         local t := TimeInSeconds() mod 60;
  62.         return DateNTime(Time()) & " and " & NumberStr(t) & if t = 1 then " second" else " seconds";
  63.     end);
  64.  
  65. constant kButton_Send := "Send Time";                                                // button names
  66. constant kButton_Receive := "Receive Time";
  67. constant kButton_Stop := "Stop";
  68.  
  69. //    -------------------------------------------------------------------------------------------------------------
  70.  
  71. DefConst('kSysBeepSyncFunc,                                                            // replaces GetRoot():SysBeep() with a similar SYNCHRONOUS version
  72.     func()
  73.     if userConfiguration.beepSound <> 'none and userConfiguration.soundVolume > 0 then
  74.             PlaySoundSync(ROM_soundoff.(userConfiguration.beepSound)));
  75.  
  76. //    -------------------------------------------------------------------------------------------------------------
  77.  
  78. OpenResFile(HOME & "IRTimeSync.rsrc");                                            // load our attention sound (played when the time has been set)
  79. DefConst('kAlarmSound, GetSound11("IRTimeSyncAlarmSound"));        // keep the size of this sample app down by using an 11Khz sample rate
  80. CloseResFile();
  81.  
  82. //    ===========================================================================================
  83.  
  84.  
  85. vIRTimeSync :=
  86.    {
  87.     viewSetupDoneScript:
  88.       func()
  89.       begin
  90.           GetRoot().extrasDrawer:Close();
  91.           :MSetPhase(nil);
  92.           :SetUpIdle(135);
  93.       end,
  94.     viewQuitScript:
  95.       func()
  96.       begin
  97.           if fEndPoint then
  98.               fEndPoint:MDisconnect();
  99.       end,
  100.     viewFlags: 576,
  101.     viewIdleScript:
  102.       func()
  103.       begin
  104.           if kDebugShowPhases then begin
  105.                   local xT := NumberStr(TimeInSeconds() mod 60);
  106.                   local xPh := if fPhase then NumberStr(fPhase) else "NIL";
  107.                   local xCon := if fEndPoint and fEndPoint.fIsConnected then "TRUE" else "FALSE";
  108.                   local xSt := if fEndPoint then NumberStr(fEndPoint:State()) else "NIL";
  109.                   SetValue(vTitle, 'text, "T: " & xT & "   Ph: " & xPh & "   Con: " & xCon & "   St: " & xSt );
  110.                   RefreshViews();
  111.               end;
  112.               
  113.           if not fPhase or fPhase = kPhase_Idle then begin
  114.                   :MSetMessage(call kMessage_IdleFunc with ());
  115.               end
  116.           
  117.           else if fPhase = kPhase_CountDown then begin
  118.                   local elapsedTime := Abs(timeinseconds() - fStartTime);
  119.                   local secondsToWait := 60 - fSeconds;
  120.                   if elapsedTime >= secondsToWait then begin
  121.                           SetTime(fMinutes + 1);
  122.                           :MSetMessage(kMessage_TimeHasBeenSet);
  123.                           PlaySound(kAlarmSound);
  124.                           fMinutes := nil;
  125.                           fSeconds := nil;
  126.                           :MSetPhase(kPhase_Disconnect);
  127.                       end
  128.                   else
  129.                       :MSetMessage(call kMessage_CountDownFunc with (secondsToWait - elapsedTime));
  130.                   end
  131.           
  132.           else if fPhase = kPhase_Send then begin
  133.                   fEndPoint :=    {    _proto:        fEndPointConfig,
  134.                                              _parent:    self    };
  135.                   local err := fEndPoint:Instantiate(fEndPoint, nil);
  136.                   if err then begin
  137.                           :MSetError(kMessage_PortInUse, err);
  138.                           :MSetPhase(nil);
  139.                       end
  140.                   else begin
  141.                       vReceiveTime:Hide();
  142.                       SetValue(vSendTime, 'text, kButton_Stop);
  143.                       :MSetMessage(kMessage_Send);
  144.                       fEndPoint:MConnect();
  145.                       fTimeoutTicks := Ticks();
  146.                       :MSetPhase(kPhase_Connecting);
  147.                   end;
  148.               end
  149.           
  150.           else if fPhase = kPhase_Connecting then begin
  151.                   if Abs(Ticks() - fTimeoutTicks) > kTimeoutTicks then begin
  152.                           :MSetMessage(kMessage_Timeout);
  153.                           call kSysBeepSyncFunc with ();
  154.                           call kSysBeepSyncFunc with ();
  155.                           :MSetPhase(kPhase_AbortQuiet);
  156.                       end
  157.                   else if fEndPoint.fIsConnected then begin
  158.                           fEndPoint:MSendTime();
  159.                           :MSetPhase(kPhase_Disconnect);
  160.                       end;
  161.               end
  162.           
  163.           else if fPhase = kPhase_Disconnect then begin
  164.                   if fEndPoint then begin
  165.                           fEndPoint:MDisconnect();
  166.                           :MSetPhase(kPhase_Disconnecting);
  167.                       end
  168.                   else
  169.                       :MSetPhase(kPhase_Disconnected);
  170.               end
  171.           
  172.           else if fPhase = kPhase_Disconnecting then begin
  173.               end
  174.           
  175.           else if fPhase = kPhase_Disconnected then begin
  176.                   SetValue(vReceiveTime, 'text, kButton_Receive);
  177.                   SetValue(vSendTime, 'text, kButton_Send);
  178.                   vReceiveTime:Show();
  179.                   vSendTime:Show();
  180.                   :MSetPhase(nil);
  181.               end
  182.           
  183.           else if fPhase = kPhase_Abort then begin
  184.                   :MSetMessage(kMessage_Stopping);
  185.                   :MSetPhase(kPhase_AbortQuiet);
  186.               end
  187.           
  188.           else if fPhase = kPhase_AbortQuiet then begin
  189.                   :MSetPhase(kPhase_Disconnect);
  190.               end
  191.           
  192.           else if fPhase = kPhase_Receive then begin
  193.                   fEndPoint :=    {    _proto:        fEndPointConfig,
  194.                                              _parent:    self    };
  195.                   local err := fEndPoint:Instantiate(fEndPoint, nil);
  196.                   if err then begin
  197.                           :MSetError(kMessage_PortInUse, err);
  198.                           :MSetPhase(nil);
  199.                       end
  200.                   else begin
  201.                       vSendTime:Hide();
  202.                       SetValue(vReceiveTime, 'text, kButton_Stop);
  203.                       :MSetMessage(kMessage_Receive);
  204.                       fEndPoint:MListen();
  205.                       fTimeoutTicks := Ticks();
  206.                       :MSetPhase(kPhase_Listening);
  207.                   end;
  208.               end
  209.           
  210.           else if fPhase = kPhase_Listening then begin
  211.                   if Abs(Ticks() - fTimeoutTicks) > kTimeoutTicks then begin
  212.                           :MSetMessage(kMessage_Timeout);
  213.                           call kSysBeepSyncFunc with ();
  214.                           call kSysBeepSyncFunc with ();
  215.                           :MSetPhase(kPhase_AbortQuiet);
  216.                       end
  217.                   else if fEndPoint.fIsConnected and fMinutes and fSeconds then begin
  218.                           if fMinutes > 0 and fSeconds >=0 and fSeconds <= 59 then
  219.                               :MSetPhase(kPhase_CountDown)
  220.                           else begin
  221.                                   :MSetMessage(kMessage_BadTime);
  222.                                   call kSysBeepSyncFunc with ();
  223.                                   call kSysBeepSyncFunc with ();
  224.                                   :MSetPhase(kPhase_AbortQuiet);
  225.                               end;
  226.                       end;
  227.               end;
  228.           
  229.           return kIdleFrequency;
  230.       end,
  231.     fPhase: nil        // holds the next phase to be executed for the idle machine,
  232.     fEndPointConfig:
  233.       {
  234.           _proto:                        protoEndpoint,
  235.           
  236.           fIsConnected:            nil,
  237.           
  238.           receiveFlags:            kFrame,
  239.           
  240.           configOptions:            [
  241.                                               {    label:        kCMSSlowIR,
  242.                                                   type:        'service,
  243.                                                   opCode:        opSetRequired,    },
  244.                                           ],
  245.                                           
  246.           exceptionHandler:        func(exception)            // deferred actions exception context is LAME -- the only action we dare take is to say we've handled the exception
  247.                                           begin
  248.                                               if HasSlot(exception, 'data)
  249.                                                   and exception.data <> nil
  250.                                                   and exception.data <> -16005                        // cancelled (not really an error)
  251.                                                   and exception.data <> -16013 then begin        // cancelled (not really an error)
  252.                                                       :MSetError(kMessage_GenericError, exception.data);
  253.                                                       call kSysBeepSyncFunc with ();
  254.                                                       call kSysBeepSyncFunc with ();
  255.                                                       call kSysBeepSyncFunc with ();
  256.                                                       if fPhase then
  257.                                                           if fPhase = kPhase_Connecting
  258.                                                           or    fPhase = kPhase_Listening
  259.                                                           or    fPhase = kPhase_CountDown then
  260.                                                               :MSetPhase(kPhase_Abort);
  261.                                                   end;
  262.                                               
  263.                                               return true;
  264.                                           end,
  265.                                           
  266.           FReceiveTime:            {    inputForm:            'string,                // data is a string of this format:  IRTimeSyncVersion1X123456Y123456Z
  267.                                               endCharacter:        $Z,
  268.                                               inputScript:            func(ep, data)
  269.                                                                           begin
  270.                                                                               ep._parent.fStartTime := TimeInSeconds();                // note the time we received the beam
  271.                                                                               ep:SetInputSpec(nil);                                                    // don't want to be retriggered
  272.                                                                               
  273.                                                                               ep._parent.fMinutes := 0;
  274.                                                                               ep._parent.fSeconds := 0;
  275.                                                                               
  276.                                                                               local p1 := StrPos(data, "X", 0);                                // suck out the version info
  277.                                                                               if p1 then begin
  278.                                                                                       if StrEqual(SubStr(data, 0, p1), "IRTimeSyncVersion1") then begin
  279.                                                                                               local p2 := StrPos(data, "Y", p1);                // suck out the time in minutes (since midnight January 1, 1904)
  280.                                                                                               if p2 then begin
  281.                                                                                                       local p3 := StrPos(data, "Z", p2);        // suck out the time in seconds (0-59)
  282.                                                                                                       if p3 then begin
  283.                                                                                                               ep._parent.fMinutes := RintToL(StringToNumber(SubStr(data, p1 + 1, p2 - p1 - 1)));
  284.                                                                                                               ep._parent.fSeconds := RintToL(StringToNumber(SubStr(data, p2 + 1, p3 - p2 - 1)));
  285.                                                                                                           end;
  286.                                                                                                       end;
  287.                                                                                           end
  288.                                                                                       else 
  289.                                                                                           ep._parent:MSetError(kMessage_BadTime, -666);
  290.                                                                                   end;
  291.                                                                           end,    },
  292.           
  293.           MSendTime:                func()
  294.                                           begin
  295.                                               local s :=    "IRTimeSyncVersion1X"                                        // IR Time Sync Version ID
  296.                                                               & NumberStr(Time()) & "Y"                                    // minutes since midnight January 1, 1904
  297.                                                               & NumberStr(TimeInSeconds() mod 60) & "Z";        // seconds past the minute (0-59)
  298.                                               :Output(s, kFrame);
  299.                                               :FlushOutput();
  300.                                           end,
  301.           
  302.           MListen:                    func()
  303.                                           begin
  304.                                               fMinutes := nil;
  305.                                               fSeconds := nil;
  306.                                               AddDeferredAction(    func(ep)
  307.                                                                               begin
  308.                                                                                   ep.fIsConnected := ep:Listen(nil) = nil;
  309.                                                                                   if ep.fIsConnected then
  310.                                                                                       ep:SetInputSpec(ep.FReceiveTime);
  311.                                                                               end,
  312.                                                                           [self]);
  313.                                           end,
  314.           
  315.           MConnect:                    func()
  316.                                           begin
  317.                                               AddDeferredAction(    func(ep)
  318.                                                                               begin
  319.                                                                                   ep.fIsConnected := ep:Connect(nil, nil) = nil;
  320.                                                                               end,
  321.                                                                           [self]);
  322.                                           end,
  323.           
  324.           MDisconnect:            func()
  325.                                           begin
  326.                                               self.nextInputSpec := nil;
  327.                                               :SetInputSpec(nil);
  328.                                               if fIsConnected and :State() = kDataXfer then
  329.                                                   :Release()
  330.                                               else
  331.                                                   :Abort();
  332.                                               AddDelayedAction(func(ep)
  333.                                                                               begin
  334.                                                                                   if ep.fIsConnected then
  335.                                                                                       ep:Disconnect();
  336.                                                                                   ep:Dispose();
  337.                                                                                   ep._parent.fEndPoint := nil;
  338.                                                                                   if ep._parent.fPhase then
  339.                                                                                       ep._parent:MSetPhase(kPhase_Disconnected);
  340.                                                                               end,
  341.                                                                           [self], 666);
  342.                                           end,
  343.       },
  344.     viewBounds: {left: 0, top: 0, right: 228, bottom: 110},
  345.     _proto: protoFloater,
  346.     MSetPhase:
  347.       func(phase)
  348.       begin
  349.           fPhase := phase;
  350.       end,
  351.     fStartTime: 0,
  352.     viewJustify: 80,
  353.     fMinutes:
  354.       nil        // nil until we receive ANY value, 0 = illegal value, other = number of minutes since midnight January 1, 1904
  355.     ,
  356.     fEndPoint: nil,
  357.     declareSelf: 'base,
  358.     viewClickScript:
  359.       func(unit)
  360.       begin
  361.           :Drag(unit, nil);
  362.       end,
  363.     debug: "vIRTimeSync",
  364.     fTimeoutTicks: 0,
  365.     MSetError:
  366.       func(message, error)
  367.       begin
  368.           :MSetMessage(message & unicodeCR & NumberStr(error));
  369.           call kSysBeepSyncFunc with ();
  370.       end,
  371.     fSeconds:
  372.       nil        // nil until we receive ANY value, 0 to 59 (inclusive) are legal values, other = illegal values
  373.     ,
  374.     MSetMessage:
  375.       func(message)
  376.       begin
  377.           SetValue(vMessage, 'text, Clone(message));
  378.           RefreshViews();
  379.       end
  380.    };
  381.  
  382. vTitle := /* child of vIRTimeSync */
  383.    {text: "",
  384.     viewBounds: {left: 0, top: 4, right: 0, bottom: 20},
  385.     viewJustify: 8388658,
  386.     _proto: protoStaticText,
  387.     debug: "vTitle"
  388.    };
  389. // View vTitle is declared to vIRTimeSync
  390.  
  391. // After Script for "vTitle"
  392. thisView := vTitle;
  393. thisView.text := kTitle;
  394.  
  395.  
  396.  
  397. vMessage := /* child of vIRTimeSync */
  398.    {text: "",
  399.     viewBounds: {left: 16, top: 24, right: 208, bottom: 55},
  400.     viewJustify: 2,
  401.     viewFont: simpleFont9,
  402.     _proto: protoStaticText,
  403.     debug: "vMessage"
  404.    };
  405. // View vMessage is declared to vIRTimeSync
  406.  
  407.  
  408.  
  409. vReceiveTime := /* child of vIRTimeSync */
  410.    {text: "",
  411.     buttonClickScript:
  412.       func()
  413.       begin
  414.           if not fPhase then
  415.               :MSetPhase(kPhase_Receive)
  416.           
  417.           else if fPhase = kPhase_Listening or fPhase = kPhase_CountDown then
  418.               :MSetPhase(kPhase_Abort);
  419.       end,
  420.     viewBounds: {left: 18, top: 57, right: 102, bottom: 77},
  421.     _proto: protoTextButton,
  422.     debug: "vReceiveTime"
  423.    };
  424. // View vReceiveTime is declared to vIRTimeSync
  425.  
  426. // After Script for "vReceiveTime"
  427. thisView := vReceiveTime;
  428. thisView.text := kButton_Receive;
  429.  
  430.  
  431.  
  432. vSendTime := /* child of vIRTimeSync */
  433.    {text: "",
  434.     buttonClickScript:
  435.       func()
  436.       begin
  437.           if not fPhase then
  438.               :MSetPhase(kPhase_Send)
  439.           
  440.           else if fPhase = kPhase_Connecting then
  441.               :MSetPhase(kPhase_Abort);
  442.       end,
  443.     viewBounds: {left: 122, top: 57, right: 206, bottom: 77},
  444.     _proto: protoTextButton,
  445.     debug: "vSendTime"
  446.    };
  447. // View vSendTime is declared to vIRTimeSync
  448.  
  449. // After Script for "vSendTime"
  450. thisView := vSendTime;
  451. thisView.text := kButton_Send;
  452.  
  453.  
  454.  
  455. vStatusBar := /* child of vIRTimeSync */
  456.    {_proto: protoStatus, debug: "vStatusBar"};
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464. // ---- Beginning of section for non used Layout files ----
  465.  
  466. // End of output